package com.rules.drools.service;

import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.rules.core.exception.CustomException;
import com.rules.core.utils.CollectionUtil;
import com.rules.core.utils.PageUtils;
import com.rules.core.utils.Query;
import com.rules.core.utils.Result;
import com.rules.drools.convert.ActionInfoConvert;
import com.rules.drools.convert.ActionParamConvert;
import com.rules.drools.dao.ActionInfoDao;
import com.rules.drools.entity.ActionInfoEntity;
import com.rules.drools.entity.ActionParamInfoEntity;
import com.rules.drools.entity.ActionParamValueInfoEntity;
import com.rules.drools.entity.SceneInfoEntity;
import com.rules.drools.vo.req.ActionInfoReqVo;
import com.rules.drools.vo.req.ActionParamReqVo;
import org.apache.commons.lang.StringUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("actionInfoService")
public class ActionInfoService extends ServiceImpl<ActionInfoDao, ActionInfoEntity> {
    @Autowired
    private Mapper dozerMapper;
    @Autowired
    private ActionParamInfoService actionParamInfoService;
    @Autowired
    private ActionParamValueInfoService actionParamValueInfoService;

    public PageUtils queryPage(Map<String, Object> params) {
        IPage<ActionInfoReqVo> page = this.baseMapper.pageAction(new Query<ActionInfoReqVo>().getPage(params));
        List<ActionInfoReqVo> records = page.getRecords();
        if (!CollectionUtil.collectionIsNull(records)) {
            records.forEach(e -> {
                List<ActionParamReqVo> actionParamItem = e.getActionParamItem();
                for (ActionParamReqVo vo : actionParamItem) {
                    List<String> collect = vo.getActionParamValueItem().stream().map(val -> val.getParamValue()).collect(Collectors.toList());
                    String join = StringUtils.join(collect, ',');
                    vo.setParamValueStr(join);
                }
            });
        }
        return new PageUtils(page);
    }

    /**
     * <p>
     * 方法说明: 获取动作列表
     *
     * @param baseRuleActionInfo 参数
     */
    public List<ActionInfoEntity> findBaseRuleActionInfoList(ActionInfoEntity baseRuleActionInfo) {
        return this.baseMapper.findBaseRuleActionInfoList(baseRuleActionInfo);
    }

    /**
     * <p>
     * 方法说明: 根据场景获取所有的动作信息
     *
     * @param sceneInfo 参数
     */
    @Cached(name = "actionInfoEntity_findRuleActionListByScene", cacheType = CacheType.LOCAL, key = "#sceneInfo.sceneIdentify", expire = 60)
    public List<ActionInfoEntity> findRuleActionListByScene(SceneInfoEntity sceneInfo) {
        return this.baseMapper.findRuleActionListByScene(sceneInfo);
    }


    /**
     * <p>
     * 方法说明: 根据规则id获取动作集合
     *
     * @param ruleId 参数
     */
    @Cached(name = "actionInfoEntity_findRuleActionListByRule", cacheType = CacheType.LOCAL, key = "#ruleId", expire = 60)
    public List<ActionInfoEntity> findRuleActionListByRule(Long ruleId) {
        return this.baseMapper.findRuleActionListByRule(ruleId);
    }

    /**
     * <p>
     * 方法说明: 查询是否有实现类的动作
     *
     * @param ruleId 规则id
     */
    @Cached(name = "actionInfoEntity_findRuleActionCountByRuleIdAndActionType", cacheType = CacheType.LOCAL, key = "#ruleId", expire = 60)
    public Integer findRuleActionCountByRuleIdAndActionType(Long ruleId) {
        return this.baseMapper.findRuleActionCountByRuleIdAndActionType(ruleId);
    }

    /**
     * @return
     * @Author gz
     * @Description 保存
     * @Date 2019/7/15 13:51
     * @Param reqVo 动作相关参数
     */
    @Transactional(rollbackFor = Exception.class)
    public Result save(ActionInfoReqVo reqVo) {
        ActionInfoEntity map = dozerMapper.map(reqVo, ActionInfoEntity.class);
        // 保存动作信息
        this.saveOrUpdate(map);
        // 动作参数
        List<ActionParamReqVo> actionParamItem = reqVo.getActionParamItem();
        if (CollectionUtil.collectionIsNull(actionParamItem)) {
            throw new CustomException("动作参数不能为空");
        }
        actionParamItem.stream().forEach(actionParamReqVo -> {
            ActionParamInfoEntity actionParam = dozerMapper.map(actionParamReqVo, ActionParamInfoEntity.class);
            actionParam.setActionId(map.getActionId());
            // 保存动作参数
            boolean save = actionParamInfoService.saveOrUpdate(actionParam);
            if (save) {
                List<ActionParamValueInfoEntity> valueItem = actionParamReqVo.getActionParamValueItem();
                // 动作参数值
                List<ActionParamValueInfoEntity> paramValue = valueItem.stream().map(entityVo -> {
                    entityVo.setActionParamId(actionParam.getActionParamId());
                    return entityVo;
                }).collect(Collectors.toList());
                // 保存动作参数值
                actionParamValueInfoService.saveOrUpdateBatch(paramValue);
            }
        });
        return Result.ok();
    }

    /**
     * @return Map<id, Name></>
     * @Author gz
     * @Description 获取动作名称，下拉选择
     * @Date 2019/7/15 15:41
     * @Param
     */
    public List<Map<String, Object>> getActionName() {
        List<ActionInfoEntity> list = this.list();
        List<Map<String, Object>> array = Lists.newArrayList();
        if (CollectionUtil.collectionIsNull(list)) {
            return array;
        }
        for (ActionInfoEntity entity : list) {
            if (entity.getIsEffect() == 1) {
                HashMap<String, Object> map = new HashMap<>(2);
                map.put("id", entity.getActionId());
                map.put("actName", entity.getActionName());
                array.add(map);
            }
        }
        return array;
    }

    /**
     * @return
     * @Author gz
     * @Description 通过动作名称获取单个信息
     * @Date 2019/7/16 10:11
     * @Param
     */
    public ActionInfoReqVo getOne(Long actionId) {
        ActionInfoEntity infoEntity = this.baseMapper.selectById(actionId);
        ActionInfoReqVo actionInfoReqVo = new ActionInfoReqVo();
        if (infoEntity != null) {
            actionInfoReqVo = ActionInfoConvert.INSTANCE.entityToVo(infoEntity);
            List<ActionParamInfoEntity> actionParamInfoEntities = actionParamInfoService.getBaseMapper().selectList(new LambdaQueryWrapper<ActionParamInfoEntity>().eq(ActionParamInfoEntity::getActionId, infoEntity.getActionId()));
            if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(actionParamInfoEntities)) {
                List<ActionParamReqVo> actionParamItem = ActionParamConvert.INSTANCE.entityToVo(actionParamInfoEntities);
                actionInfoReqVo.setActionParamItem(actionParamItem);
                List<Long> actionParamIds = actionParamInfoEntities.stream().map(ActionParamInfoEntity::getActionParamId).distinct().collect(Collectors.toList());
                List<ActionParamValueInfoEntity> actionParamValueInfoEntities = actionParamValueInfoService.getBaseMapper().selectList(new LambdaQueryWrapper<ActionParamValueInfoEntity>().in(ActionParamValueInfoEntity::getActionParamId, actionParamIds));
                if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(actionParamValueInfoEntities)){
                    Map<Long, List<ActionParamValueInfoEntity>> paramValueMap = actionParamValueInfoEntities.stream().collect(Collectors.groupingBy(ActionParamValueInfoEntity::getActionParamId));
                    for (ActionParamReqVo actionParamReqVo : actionParamItem) {
                        List<ActionParamValueInfoEntity> paramValueInfoEntityList = paramValueMap.get(actionParamReqVo.getActionParamId());
                        if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(paramValueInfoEntityList)){
                            actionParamReqVo.setActionParamValueItem(paramValueInfoEntityList);
                        }
                    }
                }
            }
        }
        return actionInfoReqVo;
    }


}
